﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Runtime.InteropServices;
using System.Data;
using System.Reflection;
using System.Threading;

namespace EquipmentConfig.Class
{
    public class Protocol
    {
        public static byte funRDI = 0x7f;
        public static byte funRDS = 0x01;

        /// <summary>
        /// 获取读取设备信息命令
        /// </summary>
        /// <returns>byte[]</returns>
        public static byte[] GetReadDeviceInfoCmd(byte funID)
        {
            List<byte> listSend = new List<byte>();
            listSend.Add(0xAA);
            listSend.Add(0x55);
            listSend.Add(0x64);
            listSend.Add(0);
            listSend.Add(8);
            listSend.Add(funID);
            ushort u = CRC16(listSend.ToArray(), listSend.Count);
            listSend.Add((byte)(u >> 0));
            listSend.Add((byte)(u >> 8));
            return listSend.ToArray();
        }
        /// <summary>
        /// 清除历史数据
        /// </summary>
        /// <param name="funID"></param>
        /// <returns></returns>
        public static byte[] RemoveHistoryInfoCmd(byte funID, List<byte> removeDate)
        {
            List<byte> listSend = new List<byte>();
            listSend.Add(0xAA);
            listSend.Add(0x55);
            listSend.Add(0x64);
            listSend.Add(0);
            listSend.Add(14);
            listSend.Add(funID);
            listSend.Add(removeDate[0]);
            listSend.Add(removeDate[1]);
            listSend.Add(removeDate[2]);
            listSend.Add(removeDate[3]);
            listSend.Add(removeDate[4]);
            listSend.Add(removeDate[5]);
            ushort u = CRC16(listSend.ToArray(), listSend.Count);
            listSend.Add((byte)(u >> 0));
            listSend.Add((byte)(u >> 8));
            return listSend.ToArray();
        }

        /// <summary>
        /// 配置命令
        /// </summary>
        /// <param name="funID">功能ID，0x03保存设备配置，0x06设备时间设置</param>
        /// <param name="byteData">配置数据字节</param>
        /// <returns>byte[]</returns>
        public static byte[] GetWriteDeviceCmd(byte funID, byte[] byteData)
        {
            List<byte> listSend = new List<byte>();
            listSend.Add(0xAA);
            listSend.Add(0x55);
            listSend.Add(0x64);
            listSend.AddRange(BitConverter.GetBytes((ushort)(byteData.Length + 8)).Reverse<byte>());
            listSend.Add(funID);
            listSend.AddRange(byteData);
            ushort u = CRC16(listSend.ToArray(), listSend.Count);
            listSend.Add((byte)(u >> 0));
            listSend.Add((byte)(u >> 8));
            //Messages.ShowAlertDialog("读取设备信息1！" + string.Join(",", ConvertData(listSend.ToArray())), true);
            Thread.Sleep(200);
            return listSend.ToArray();
        }

        /// <summary>
        /// 传感器调试配置命令
        /// </summary>
        /// <param name="intType">传感器类型</param>
        /// <param name="isOpen">true:开始调试,false:退出调试</param>
        /// <returns>byte[]</returns>
        public static byte[] GetDeviceDebugCmd(int intType, int index, bool isOpen)
        {
            List<byte> listData = new List<byte>();
            if (isOpen)
            {
                listData.Add(0x01);
            }
            else
            {
                listData.Add(0x00);
            }
            listData.Add((byte)intType);
            listData.Add((byte)index);
            listData.Add(0x00);
            listData.Add(0x02);
            //Protocol.GetWriteDeviceCmd(0x04, listData.ToArray())
            return Protocol.GetWriteDeviceCmd(0x04, listData.ToArray());
        }

        /// <summary>
        /// 设备升级命令
        /// </summary>
        /// <param name="byteData">配置数据字节</param>
        /// <param name="indexPackages">当前包数</param>
        /// <param name="totalPackages">总包数</param>
        /// <returns>byte[]</returns>
        public static byte[] GetWriteDeviceUpgradeCmd(byte[] byteData, int indexPackages, int totalPackages)
        {
            List<byte> listSend = new List<byte>();
            listSend.Add(0xAA);
            listSend.Add(0x55);
            listSend.Add(0x64);
            listSend.AddRange(BitConverter.GetBytes((ushort)(byteData.Length + 6 + 8)).Reverse<byte>());
            listSend.Add(0x05);
            listSend.AddRange(BitConverter.GetBytes((ushort)indexPackages).Reverse<byte>());
            listSend.AddRange(BitConverter.GetBytes((ushort)totalPackages).Reverse<byte>());
            ushort u = CRC16(byteData, byteData.Length);
            listSend.Add((byte)(u >> 0));
            listSend.Add((byte)(u >> 8));
            listSend.AddRange(byteData);
            u = CRC16(listSend.ToArray(), listSend.Count);
            listSend.Add((byte)(u >> 0));
            listSend.Add((byte)(u >> 8));
            return listSend.ToArray();
        }

        /// <summary>
        /// CRC16校验
        /// </summary>
        /// <param name="dataBytes">数据字节</param>
        /// <param name="count">数据长度</param>
        /// <returns>ushort</returns>
        public static ushort CRC16(byte[] dataBytes, int count)
        {
            ushort crc = 0xffff;
            ushort polynom = 0xA001;

            for (int i = 0; i < count; i++)
            {
                crc ^= dataBytes[i];
                for (int j = 0; j < 8; j++)
                {
                    if ((crc & 0x01) == 0x01)
                    {
                        crc >>= 1;
                        crc ^= polynom;
                    }
                    else
                    {
                        crc >>= 1;
                    }
                }
            }
            return crc;
        }

        /// <summary>
        /// 检查CRC
        /// </summary>
        /// <param name="byteData">数据字节</param>
        /// <returns>true,false</returns>
        public static bool CheckCRC(byte[] byteData)
        {
            ushort u = CRC16(byteData, byteData.Length - 2);
            byte crc1 = (byte)(u >> 0);
            byte crc2 = (byte)(u >> 8);
            if (crc1 == byteData[byteData.Length - 2] && crc2 == byteData[byteData.Length - 1])
            {
                return true;
            }
            return false;
        }

        /// <summary>
		/// 结构体转byte数组
		/// </summary>
		/// <param name="structObj">结构体</param>
		/// <returns>byte数组</returns>
		public static byte[] StructToBytes(object structObj)
        {
            //结构体的大小
            int size = Marshal.SizeOf(structObj);
            //创建byte数组
            byte[] bytes = new byte[size];
            //分配结构体大小的内存空间
            IntPtr structPtr = Marshal.AllocHGlobal(size);
            //将结构体拷到分配好的内存空间
            Marshal.StructureToPtr(structObj, structPtr, false);
            //从内存空间拷到byte数组
            Marshal.Copy(structPtr, bytes, 0, size);
            //释放内存空间
            Marshal.FreeHGlobal(structPtr);
            return bytes;
        }

        /// <summary>
        /// byte数组转结构体
        /// </summary>
        /// <param name="bytes">byte数组</param>
        /// <param name="type">结构体类型</param>
        /// <returns>转换后的结构体</returns>
        public static object BytesToStuct(byte[] bytes, Type type)
        {
            //结构体的大小
            int size = Marshal.SizeOf(type);
            //byte数组长度小于结构体的大小
            if (size > bytes.Length)
            {
                return null;
            }
            //分配结构体大小的内存空间
            IntPtr structPtr = Marshal.AllocHGlobal(size);
            //将byte数组拷到分配好的内存空间
            Marshal.Copy(bytes, 0, structPtr, size);
            //将内存空间转换为目标结构体
            object obj = Marshal.PtrToStructure(structPtr, type);
            //释放内存空间
            Marshal.FreeHGlobal(structPtr);
            return obj;
        }

        public static string ConvertData(Byte[] data)
        {
            try
            {
                StringBuilder sb = new StringBuilder();
                foreach (Byte b in data)
                {
                    sb.Append(Convert.ToString(b, 16).PadLeft(2, '0'));
                }
                return sb.ToString();
            }
            catch { return string.Empty; }
        }

        /// <summary>
        /// 16进制原码字符串转字节数组
        /// </summary>
        /// <param name="hexString">"AABBCC"或"AA BB CC"格式的字符串</param>
        /// <returns></returns>
        public static byte[] ConvertHexStringToBytes(string hexString)
        {
            hexString = hexString.Replace(" ", "");
            if (hexString.Length % 2 != 0)
            {
                throw new ArgumentException("参数长度不正确");
            }

            byte[] returnBytes = new byte[hexString.Length / 2];
            for (int i = 0; i < returnBytes.Length; i++)
            {
                returnBytes[i] = Convert.ToByte(hexString.Substring(i * 2, 2), 16);
            }
            return returnBytes;
        }
    }
}
